package org.bitmap.mm.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.entity.HttpEntityWrapper;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.text.format.DateUtils;
import android.util.Log;

/**
 * HTTP相关通用方法. dai_rui_lin Email:hljdrl@gmail.com
 * */
 class HttpLove {
	 
	private static final String TAG = "HttpLove";
	private static final int SECOND_IN_MILLIS = (int) DateUtils.SECOND_IN_MILLIS;

	private static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
	private static final String ENCODING_GZIP = "gzip";


	public static HttpClient getHttpClient1(Context mCm) {
		final HttpParams params = new BasicHttpParams();
		HttpConnectionParams
				.setConnectionTimeout(params, 10 * 1000);
		HttpConnectionParams.setSoTimeout(params, 50 * SECOND_IN_MILLIS);
		HttpConnectionParams.setSocketBufferSize(params, 8192);
		HttpProtocolParams.setUserAgent(params, buildUserAgent(mCm));
		final DefaultHttpClient client = new DefaultHttpClient(params);
		return client;
	}

	/**
	 * Generate and return a {@link HttpClient} configured for general use,
	 * including setting an application-specific user-agent string.
	 */
	public static HttpClient getHttpClient(Context context) {
		final HttpParams params = new BasicHttpParams();

		// Use generous timeouts for slow mobile networks
		HttpConnectionParams
				.setConnectionTimeout(params, 10 * SECOND_IN_MILLIS);
		HttpConnectionParams.setSoTimeout(params, 40 * SECOND_IN_MILLIS);

		HttpConnectionParams.setSocketBufferSize(params, 8192);
		HttpProtocolParams.setUserAgent(params, buildUserAgent(context));

		final DefaultHttpClient client = new DefaultHttpClient(params);

		client.addRequestInterceptor(new HttpRequestInterceptor() {
			public void process(HttpRequest request, HttpContext context) {
				// Add header to accept gzip content
				if (!request.containsHeader(HEADER_ACCEPT_ENCODING)) {
					request.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
				}
			}
		});

		client.addResponseInterceptor(new HttpResponseInterceptor() {
			public void process(HttpResponse response, HttpContext context) {
				// Inflate any responses compressed with gzip
				final HttpEntity entity = response.getEntity();
				final Header encoding = entity.getContentEncoding();
				if (encoding != null) {
					for (HeaderElement element : encoding.getElements()) {
						if (element.getName().equalsIgnoreCase(ENCODING_GZIP)) {
							response.setEntity(new InflatingEntity(response
									.getEntity()));
							break;
						}
					}
				}
			}
		});

		return client;
	}
	
	/**
	 * Generate and return a {@link HttpClient} configured for general use,
	 * including setting an application-specific user-agent string.
	 */
	public static HttpClient getHttpClient(ClientConnectionManager dccn,Context context) {
		final HttpParams params = new BasicHttpParams();

		// Use generous timeouts for slow mobile networks
		HttpConnectionParams
				.setConnectionTimeout(params, 20 * SECOND_IN_MILLIS);
		HttpConnectionParams.setSoTimeout(params, 50 * SECOND_IN_MILLIS);

		HttpConnectionParams.setSocketBufferSize(params, 8192);
		HttpProtocolParams.setUserAgent(params, buildUserAgent(context));

		final DefaultHttpClient client = new DefaultHttpClient(dccn,params);

		client.addRequestInterceptor(new HttpRequestInterceptor() {
			public void process(HttpRequest request, HttpContext context) {
				// Add header to accept gzip content
				if (!request.containsHeader(HEADER_ACCEPT_ENCODING)) {
					request.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
				}
			}
		});

		client.addResponseInterceptor(new HttpResponseInterceptor() {
			public void process(HttpResponse response, HttpContext context) {
				// Inflate any responses compressed with gzip
				final HttpEntity entity = response.getEntity();
				final Header encoding = entity.getContentEncoding();
				if (encoding != null) {
					for (HeaderElement element : encoding.getElements()) {
						if (element.getName().equalsIgnoreCase(ENCODING_GZIP)) {
							response.setEntity(new InflatingEntity(response
									.getEntity()));
							break;
						}
					}
				}
			}
		});

		return client;
	}

	/**
	 * Build and return a user-agent string that can identify this application
	 * to remote servers. Contains the package name and version code.
	 */
	private static String buildUserAgent(Context context) {
		try {
			final PackageManager manager = context.getPackageManager();
			final PackageInfo info = manager.getPackageInfo(
					context.getPackageName(), 0);

			// Some APIs require "(gzip)" in the user-agent string.
			return info.packageName + "/" + info.versionName + " ("
					+ info.versionCode + ") (gzip)";
		} catch (NameNotFoundException e) {
			return null;
		}
	}

	/**
	 * Simple {@link HttpEntityWrapper} that inflates the wrapped
	 * {@link HttpEntity} by passing it through {@link GZIPInputStream}.
	 */
	private static class InflatingEntity extends HttpEntityWrapper {
		public InflatingEntity(HttpEntity wrapped) {
			super(wrapped);
		}

		@Override
		public InputStream getContent() throws IOException {
			return new GZIPInputStream(wrappedEntity.getContent());
		}

		@Override
		public long getContentLength() {
			return -1;
		}
	}

	public static byte[] readStream(InputStream inStream) throws Exception {
		ByteArrayOutputStream outstream = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = -1;
		while ((len = inStream.read(buffer)) != -1) {
			outstream.write(buffer, 0, len);
		}
		outstream.close();
		inStream.close();

		return outstream.toByteArray();
	}
	
	public static byte[] getHttpData(Context context,String url) throws ClientProtocolException, IOException
	{
		byte bytes[]=null;
		 final HttpClient httpClient = HttpLove.getHttpClient(
                 context.getApplicationContext());
         final HttpResponse resp = httpClient.execute(new HttpGet(url));
         final HttpEntity entity = resp.getEntity();

         final int statusCode = resp.getStatusLine().getStatusCode();
         if (statusCode != HttpStatus.SC_OK || entity == null) {
             return null;
         }
         bytes = EntityUtils.toByteArray(entity);
         return bytes;
	}
	
	public static String getHttpDataAsString(Context context,String url) throws ClientProtocolException, IOException
	{
		byte bytes[]=null;
		 final HttpClient httpClient = HttpLove.getHttpClient(
                 context.getApplicationContext());
         final HttpResponse resp = httpClient.execute(new HttpGet(url));
         final HttpEntity entity = resp.getEntity();

         final int statusCode = resp.getStatusLine().getStatusCode();
         if (statusCode != HttpStatus.SC_OK || entity == null) {
             return null;
         }
         bytes = EntityUtils.toByteArray(entity);
         if(bytes!=null){
         return new String(bytes);
         }else {
        	 return null;
         }
	}

	/**
	 * 
	 * */
	public static byte[] readGZIPInputStream(InputStream inStream)
			throws IOException {
		GZIPInputStream gzipStream = new GZIPInputStream(inStream);
		ByteArrayOutputStream outstream = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = -1;
		while ((len = gzipStream.read(buffer)) != -1) {
			outstream.write(buffer, 0, len);
		}
		outstream.close();
		inStream.close();
		return outstream.toByteArray();
	}

	public static void writeGZIPOutputStream(OutputStream outStream, byte[] send)
			throws IOException {
		GZIPOutputStream gzipStream = new GZIPOutputStream(outStream);
		gzipStream.write(send, 0, send.length);
		Thread.yield();
		gzipStream.close();
		outStream.close();
	}
	
	
	/**
	 * 
	 * 判断本地是否联网,如果没有联网直接返回
	 * 
	 * @return true 有网络 false 没有网
	 */
	public static boolean isNetWorkAvailable(Context context) {
		ConnectivityManager connectivity = (ConnectivityManager) context
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo info = connectivity.getActiveNetworkInfo();
		if (info == null || info.getState() != State.CONNECTED) {
			return false;
		}
		return true;
	}
	
	private static final void onInitFiles(File file)
	{
		List<File> mFiles = new ArrayList<File>();
		File tmpFile = file;
		try{
		while(!tmpFile.exists()){
			mFiles.add(tmpFile);
			tmpFile = tmpFile.getParentFile();
		}
		for(int i=mFiles.size();i>0;i--){
			File mFm = mFiles.get(i);
			if(!mFm.exists()){
				mFm.mkdir();
			}
		}
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}
	/**
	 * 下载图片保存在本地文件
	 * 
	 * @param context
	 * @param urlString
	 * @return
	 */
	static synchronized File downloadBitmapToFile(Context context,
			String url) {
		if(url==null||url.equals("")){
			return new File("");
		}
		final File cacheDir = FileLove.getExternalCacheDir(context);
		onInitFiles(cacheDir);
		
		
		String urlString = url.replaceAll(" ", "");
		FileOutputStream out = null;
		final File cachedFile = new File(cacheDir,
				FileLove.hashKeyForDisk(urlString));
		if (cachedFile.exists()) {
			Log.v(TAG, "downloadBitmap - 已存在 - " + urlString);
			return cachedFile;
		}
		try {
			Log.v(TAG, "downloadBitmap - FileName - " + cachedFile.toString());
			//
			final HttpClient httpClient = HttpLove.getHttpClient(context
					.getApplicationContext());
			
			StringBuilder builder = new StringBuilder();
			if(urlString.indexOf("http://") == -1){
				builder.append("http://");
			}
			builder.append(urlString);
			String imgUrl = builder.toString();
			imgUrl = imgUrl.replace("\\", "/");
			
			final HttpResponse resp = httpClient
					.execute(new HttpGet(imgUrl));
			final HttpEntity entity = resp.getEntity();

			final int statusCode = resp.getStatusLine().getStatusCode();
			if (statusCode == HttpStatus.SC_OK || entity != null) {
				final byte[] respBytes = EntityUtils.toByteArray(entity);
				//
				if (cachedFile != null && respBytes != null
						&& respBytes.length > 0) {
					cachedFile.getParentFile().mkdirs();
					cachedFile.createNewFile();
					out = new FileOutputStream(cachedFile);
					out.write(respBytes);
				}
			}
		} catch (final IOException e) {
			e.printStackTrace();
			Log.e(TAG, "Error in downloadBitmap - ", e);
		} catch (Exception ex) {
			ex.printStackTrace();
			Log.e(TAG, "Error in downloadBitmap - ", ex);
			System.gc();
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (final IOException e) {
					Log.e(TAG, "Error in downloadBitmap - ", e);
				}
			}
		}
		return cachedFile;
	}


}
